﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using HoldemGame;

namespace HoldemView
{

    public partial class PlayerPanel : Panel
    {
        private GameSeat seat;
        private HoldemTableDirector director;
        private bool _updateCombo;
        private CardSet newCards = null;

        public GamePlayer Player
        {
            get { return seat.Player;}
        }

        public GameSeat Seat
        {
            get { return seat; }
            set { seat = value; 
                if(seat.Player!=null)
                    PlayerChanged(); }
        }

        public HoldemTableDirector Director { get { return director; } set { director = value; } }

        public void SetMiniView(bool mini)
        {
            if (mini)
                this.Height = this.rtInfo.Top;
            else
                this.Height = HoldemTable.PlayerPanelHeight;
        }

        public ToolStripMenuItem Menu { get { return msPlayerMenu.Items[0] as ToolStripMenuItem; } }

        public PlayerPanel(HoldemTableDirector dir)
        {
            director = dir;
            InitializeComponent();
            this.cbPlayer.SelectedIndexChanged += new EventHandler(PlayerCombo_SelIndexChanged);
            ToolStripDirector.SetTag(Menu, this, true);
            Director.SubscribePlayerMenu(Menu);
            this.rtCards.GotFocus += new EventHandler(rtCards_GotFocus);
            this.rtCards.LostFocus += new EventHandler(rtCards_LostFocus);
            this.rtCards.KeyPress += new KeyPressEventHandler(rtCards_KeyPress);
            this.btnGO.Click += new EventHandler(btnGO_Click);
            this.rtInfo.Text = "";
            this.rtInfo.ReadOnly = true;
            this.rtBank.ReadOnly = true;
            this.rbFold.Checked = true;

            this.btnCards.Click += new EventHandler(btnCards_Click);
        }

        void btnCards_Click(object sender, EventArgs e)
        {
            UpdateCards(false);
            ToolStripDropDown tsdd = 
                CardDropDown.DropDown(rtCards);
            tsdd.Closed += new ToolStripDropDownClosedEventHandler(tsdd_Closed);
        }

        void tsdd_Closed(object sender, ToolStripDropDownClosedEventArgs e)
        {
            ParseCards();
            UpdateCards(true); 
        }

        int UserAction
        {
            get {
                if (this.rbCall.Checked)
                    return BrainAction.CALL;
                else if (this.rbRaise.Checked)
                    return BrainAction.RAISE;
                else if (this.rbFold.Checked)
                    return BrainAction.FOLD;
                else if (this.rbBlind.Checked)
                    return BrainAction.BLIND;
                throw new InvalidOperationException();
            
            }
        }

        void btnGO_Click(object sender, EventArgs e)
        {
            this.btnGO.Enabled = false;

            if (this.rbCall.Checked)
                Director.Call();
            else if (this.rbRaise.Checked)
                Director.Raise();
            else if (this.rbFold.Checked)
                Director.Fold();
            else if (this.rbBlind.Checked)
                Director.Blind();
            else
                throw new InvalidOperationException();
        }

        void rtCards_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == '\r')
            {
                //ParseCards();
                BeginInvoke(new EventHandler(delegate(object obj, EventArgs args) { this.Focus(); }));
            }
        }

        public int Verify(List<Exception> errs)
        {
            if (null != newCards)
                try
                {
                    return Director.VerifyCards(Player,newCards,errs);
                }
                catch (Exception e)
                {
                    if(null!=errs)
                        errs.Add(e);
                    return 1;
                }
            return 0;
        }

        public void Commit()
        {
            if (null != newCards)
                if(0==Verify(null))
            {
                Director.PocketCards(Player,newCards);
                newCards = null;
                Director.CommitCount--;
            }
        }

        void UpdateCards(bool useIcon)
        {
            int toShow = Player.VisiblePocketCardsCount;
            
            if (Director.GameOptions.IsShowAllCards)
                toShow = Player.PocketCards.Count;

            CardFormatter.SetCards(rtCards, Cards, Cards.Count, toShow, useIcon, newCards!=null);
        }

        CardSet Cards { get { return newCards != null ? newCards : Player.PocketCards; } }

        void ParseCards()
        {
            try
            {
                CardSet cs = CardSet.ParseAll(rtCards.Text,2);
                if (null == newCards)
                    Director.CommitCount++;
                newCards = cs;
            }
            catch (InvalidOperationException ex)
            {
                //MessageBox.Show(ex.ToString());
                Layers.MyLogger.WriteLine(Player.ToString()+":"+ ex.ToString());
            }
        }

        void rtCards_LostFocus(object sender, EventArgs e)
        {
            if(!rtCards.ReadOnly)
                ParseCards();
            UpdateCards(true); 
        }

        void rtCards_GotFocus(object sender, EventArgs e)
        {
            UpdateCards(false);
        }

        void PlayerCombo_SelIndexChanged(object sender, EventArgs e)
        {
            if (!_updateCombo && null != director)
                director.ReplacePlayer(this, this.cbPlayer.SelectedItem as GamePlayer);
        }

        public int AddPlayer(GamePlayer p)
        {
            int idx = this.cbPlayer.Items.Add(p);
            return idx;
        }

        void UpdatePlayersCombo()
        {
            _updateCombo = true;
            this.cbPlayer.Items.Clear();
            AddPlayer(Player);
            if(null!=director)
                foreach (GamePlayer p in director.GetAvailablePlayers(this))
                {
                    if (!this.cbPlayer.Items.Contains(p))
                        AddPlayer(p);
                }
            this.cbPlayer.SelectedIndex = 0;
            _updateCombo = false;
        }

        public void PlayerChanged()
        {
            Menu.Text= Player.Position+":";

            director.UpdatePlayerMenu(this.msPlayerMenu.Items[0] as ToolStripMenuItem, this);

            string[] lines = new string[]{
                "S$"+Math.Round(Player.Stake),
                "B$"+Math.Round(Player.Bank),
            };

            this.rtBank.Lines = lines;
            this.rtBank.Select(0, lines[0].Length);
            this.rtBank.SelectionColor = Color.Brown;

            //if (0 == this.cbPlayer.Items.Count)
            //{
            //    int idx = this.cbPlayer.Items.Add(player.ID);
            //    //this.cbPlayer.Items.Add("Me");
            //    this.cbPlayer.SelectedIndex = idx;
            //}
            UpdatePlayersCombo();

            Director.UpdatePlayerMenu(Menu, this);

            CardFormatter.UpdateText(this.rtState, Player.StateString());
            CardFormatter.UpdateText(this.rtInfo, HistoryString(Player)+"\n"+Player.HandString);

            this.rtCards.ReadOnly = !Director.GameOptions.IsShowAllCards;
            this.btnCards.Enabled = !this.rtCards.ReadOnly;

            UpdateCards(!this.rtCards.Focused);

            UpdateAction(false);

            Color bkgr = Player.IsActive ? Color.LightBlue : SystemColors.ButtonFace;
            CardFormatter.SetBkgr(this, bkgr);

            Color act = Player.IsCurrent ? (Director.IsManualStep() ? Color.White : Color.Orange) : bkgr;
            this.btnGO.BackColor = act;
            this.cbPlayer.BackColor = act;

        }


        bool UserActionIsCorrect()
        {
            if (rbCall.Checked && !rbCall.Enabled)
                return false;
            if (rbRaise.Checked && !rbRaise.Enabled)
                return false;
            if (rbFold.Checked && !rbFold.Enabled)
                return false;
            if (rbBlind.Checked && !rbBlind.Enabled)
                return false;
            return true;
        }

        public void UpdateAction(bool keepUser)
        {
            this.rbCall.Enabled = !Seat.IsFree && Player.IsCurrent && Director.CanCall();
            this.rbFold.Enabled = !Seat.IsFree && Player.IsCurrent && Director.CanFold();
            if (rbFold.Enabled)
            {
                //Layers.MyLogger.WriteLine(Player + ":" + Player.IsCurrent + ": ENA");
            }
            this.rbRaise.Enabled = !Seat.IsFree && Player.IsCurrent && Director.CanRaise();
            this.rbBlind.Enabled = !Seat.IsFree && Player.IsCurrent && Director.IsBlind();

            bool canGo = !Seat.IsFree && Player.IsCurrent && Director.IsManualStep() && !Director.IsRunning()
                    && UserActionIsCorrect();

            this.btnGO.Enabled = canGo;

            this.rbCall.Text = this.rbCall.Enabled ? "CALL $"+Director.State.GetCallAmount(Player):"CALL";
            this.rbRaise.Text = this.rbCall.Enabled ? "RAISE $" + Director.State.GetRaiseAmount(Player) : "RAISE";

            BrainAction ba = null;
            if(!Seat.IsFree)
                ba = Player.LastAction;

            if (!keepUser)
            {
                //if(ba==null)
                //    if(canGo)
                 //       ba=BrainAction.Fold;

                if (ba != null)
                {
                    switch (ba.ID)
                    {
                        case BrainAction.FOLD: 
                                this.rbFold.Checked = true; 
                        break;
                        case BrainAction.CALL: 
                            //if(this.rbCall.Enabled)
                                this.rbCall.Checked = true;
                            //else
                            //    this.rbFold.Checked = true;
                            break;
                        case BrainAction.RAISE:
                            //if (this.rbRaise.Enabled)
                                this.rbRaise.Checked = true;
                            //else
                             //   this.rbFold.Checked = true;
                            break;
                        case BrainAction.BLIND:
                           // if (this.rbBlind.Enabled)
                                this.rbBlind.Checked = true;
                            //else
                               // this.rbFold.Checked = true;
                            break;
                        default: throw new InvalidOperationException();
                    }
                    //if (Director.IsManualStep())
                     //   if (rbBlind.Checked)
                         //   rbFold.Checked = true;
                        
                }
                else
                {
                    //this.rbFold.Checked = true;
                    //this.rbFold.Checked = false;
                }
            }

            BrainAction wants = null;
            if (!Seat.IsFree && Player.IsCurrent)
                if (Player.IsActionReady)
                    wants = Director.State.Players.Current.BrainAction;

            int id = wants!=null ? wants.ID : -1;

            this.rbCall.Font = new Font(this.rbCall.Font, id == BrainAction.CALL?FontStyle.Bold:FontStyle.Regular);
            this.rbRaise.Font = new Font(this.rbRaise.Font, id == BrainAction.RAISE? FontStyle.Bold : FontStyle.Regular);
            this.rbFold.Font = new Font(this.rbFold.Font, id == BrainAction.FOLD? FontStyle.Bold : FontStyle.Regular);
        
        }

        private string PlayerString(GamePlayer p)
        {
            return p.ID + ":" + p.Brains.ID;
        }

        private bool IsActionVisible(HoldemAction ha)
        {
            switch(ha.ID)
            {
                case HoldemActionID.CURRENT: return false;
            }
            return true;
        }

        private string HistoryString(GamePlayer p)
        {
            StringBuilder sb = new StringBuilder();
            foreach (HoldemAction ha in p.History)
                if(IsActionVisible(ha))
            {
                sb.Append("\n");
                sb.Append(ha.ToString());
            }
            return sb.ToString();
        }

       
        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void label1_Click_1(object sender, EventArgs e)
        {

        }

        private void msMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }

        private void rtCards_TextChanged(object sender, EventArgs e)
        {

        }

        private void rbCall_CheckedChanged(object sender, EventArgs e)
        {

        }
    }
}
